談到現代化,很容易接著想到微服務。不過,服務一拆,網路呼叫、部署、資料一致性與監控,也都要有人維護。所以我會先問:哪些功能真的需要分開修改、分開上線?
我想先把拆分後的日常工作攤開來看。原本在程式裡呼叫一個方法,之後可能要透過網路;原本部署一次,之後可能要管理好幾個版本;原本一筆資料庫交易,之後也可能需要補償。把這些想清楚,再選架構,心裡會比較有底。
| 條件 | 模組化單體較適合 | 微服務較適合 |
|---|---|---|
| 團隊 | 小型、共同發佈 | 多團隊、能獨立負責 |
| 業務邊界 | 尚未穩定 | 邊界與責任清楚 |
| 部署需求 | 可共同部署 | 需獨立擴展與發佈 |
| 資料交易 | 強一致、跨模組頻繁 | 可接受最終一致性 |
| 維運能力 | 監控與自動化有限 | 已有成熟平台能力 |
這五項我會一項一項確認。尤其是維運能力:監控、告警、自動部署與故障演練還沒準備好時,先把服務拆散,之後查問題可能更辛苦。

圖 Day 05-1:架構選型決策。
如果一個功能該歸哪個模組還常常在變,例如信用額度檢查該屬於訂單還是客戶,太早把它做成獨立服務,每次搬動都得連 API 契約、兩邊部署和整合測試一起改;先留在同一個程式的模組裡,搬動只是調整程式結構,一次建置、一次測試就能驗完,成本低很多。所以我會先看邊界穩不穩定,再往下判斷。
所以,這個系列會用混合的方式來討論。高度相關、變動不多的功能,可以先保留在模組化結構;ERP 格式與介面細節,則集中到 Adapter。
像訂單與出貨單、退貨單這些會一起變動的資料,就留在同一個訂單服務;訂單與庫存目前則是兩個服務,訂單透過 REST 呼叫庫存服務確認可用量;庫存服務連不上時,circuit breaker 的降級回應會讓這筆訂單以「庫存服務暫時不可用」被擋下,而不是悄悄建立一筆缺料的訂單,所以拆開仍可接受。
ERP 的 SOAP 欄位與狀態碼,則只在兩個轉接服務出現:Adapter 負責寫入型轉送與帶業務解析的查詢,另一個查詢代理服務負責泛用查詢。至於哪一部分值得獨立出來,還是要依專案的需要決定。
像 ERP 介面的變動來自平台外部,集中在 Adapter 處理,就比較容易知道影響會落在哪裡。可以分開照顧穩定與仍在調整的部分,也是我喜歡這種安排的一個原因。
即使先維持單體,我也會把模組分工做好。資料表由誰負責、模組透過什麼介面合作、哪些呼叫不允許,都先訂清楚,再用契約確認。之後有獨立部署、擴展或安全隔離的需要,再來評估拆分。
邊界的維護,不能只靠大家記得。所以我認為,規則能在建置時被檢查,是很重要的一步。例如跨 Schema 存取或繞過 Adapter 的程式一出現,測試就能提醒團隊。目前平台只有 EDI 對帳模組有一支靜態掃描測試,守著「不得自建 SOAP client」;其餘邊界仍靠 Review。
模組之間透過明確介面合作,資料責任與同步、事件處理也先分清楚。這些準備做好,日後真的要抽成服務,就能少一些重新釐清與整理的工作。
| 取捨 | 這樣選的理由 | 何時要重新評估 |
|---|---|---|
| 先維持模組化單體 | 邊界未穩定時,模組內調整成本遠低於跨服務調整 | 某模組確實需要獨立部署、擴展或安全隔離時 |
| 採混合架構而非全面微服務 | 只為真正需要獨立性的能力付出分散式成本 | 保留在單體內的模組開始互相阻擋發佈時 |
| ERP 細節集中在轉接層 | 變動來源在外部,集中處理才能控制影響範圍 | Adapter 成為效能瓶頸,或開始累積業務規則時 |
| 邊界規則先靠模組相依與 Review | 文件規範會被繞過;模組相依在編譯期就擋得住跨服務引用 | 單一服務內部開始出現越界、Review 擋不住時(屆時導入架構測試) |
業務之後會改變,保留原本的想法,才比較容易判斷現在需要調整哪裡。所以拆分時的理由與邊界假設,也一起記錄。
邊界是否合適,可以從變更紀錄檢查,不必等到出問題:
| 指標 | 計算方式 | 想回答的問題 |
|---|---|---|
| 每需求涉及服務數 | 單一需求平均變更的服務數 | 邊界是否切在業務會一起變動的位置? |
| 共同部署比例 | 需同時部署的服務數/該次變更服務數 | 是否只是把單體切開,卻仍綁在一起發佈? |
| 跨服務交易比例 | 需跨服務保證一致性的交易/全部交易 | 是否過早拆分了強一致的流程? |
| 跨模組越界次數 | Review 中攔下的越界修改次數 | 邊界規範是否仍被遵守? |
如果每次改需求都要一起動到好幾個服務,我會先回來看看當初怎麼劃分。這些變更紀錄,可以幫助我們判斷,現在的邊界是不是還適合。
今天整理下來,我最在意的還是:這個架構,團隊能不能持續把它維護好?先把分工做清楚,也保留調整的空間。下一篇,再把這些角色放進同一張平台藍圖裡。